package hlPay

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"

	"gitee.com/wangshh_123/cross-pay-go/src/config"
)

// HlPayUtils 处理 hlPay 的认证和签名相关功能
type HlPayUtils struct {
	clientID     string // hlPay 客户端 ID
	clientKey    string // hlPay 客户端密钥
	clientSecret string // hlPay 客户端密钥
	gatewayURL   string // hlPay 网关地址
}

// NewHlPayUtils 创建 HlPayUtils 的新实例
func NewHlPayUtils() (*HlPayUtils, error) {
	// 检查配置是否已初始化
	if config.GlobalConfig.HlPay.ClientID == "" {
		return nil, fmt.Errorf("hlpay clientid is not configured")
	}

	if config.GlobalConfig.HlPay.ClientKey == "" {
		return nil, fmt.Errorf("hlpay clientkey is not configured")
	}

	if config.GlobalConfig.HlPay.ClientSecret == "" {
		return nil, fmt.Errorf("hlpay clientSecret is not configured")
	}

	if config.GlobalConfig.HlPay.GatewayURL == "" {
		return nil, fmt.Errorf("hlpay gateway_url is not configured")
	}

	return &HlPayUtils{
		clientID:     config.GlobalConfig.HlPay.ClientID,
		clientKey:    config.GlobalConfig.HlPay.ClientKey,
		clientSecret: config.GlobalConfig.HlPay.ClientSecret,
		gatewayURL:   config.GlobalConfig.HlPay.GatewayURL,
	}, nil
}

// IsTokenValid 检查令牌是否有效
func (h *HlPayUtils) IsTokenValid(expiresIn int64) bool {
	return time.Now().Unix() < expiresIn
}

// GetAccessToken 获取访问令牌
// 返回:
//   - string: 访问令牌
//   - string: 刷新令牌（hlPay可能为null）
//   - int64: 过期时间（秒）
//   - int64: 刷新令牌过期时间（秒）
//   - error: 错误信息
func (h *HlPayUtils) GetAccessToken() (string, string, int64, int64, error) {
	url := fmt.Sprintf("%s/hlPayApi/auth/token", h.gatewayURL)

	// 构造请求体
	tokenReq := TokenRequest{
		GrantType:    "api",
		ClientID:     h.clientID,
		ClientSecret: h.clientSecret,
		ClientKey:    h.clientKey,
	}

	reqBody, err := json.Marshal(tokenReq)
	if err != nil {
		return "", "", 0, 0, fmt.Errorf("marshal request body failed: %v", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqBody))
	if err != nil {
		return "", "", 0, 0, fmt.Errorf("create request failed: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "*/*")
	req.Header.Set("User-Agent", "Apifox/1.0.0 (https://apifox.com)")

	client := &http.Client{
		Timeout: 10 * time.Second,
	}
	resp, err := client.Do(req)
	if err != nil {
		return "", "", 0, 0, fmt.Errorf("do request failed: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", "", 0, 0, fmt.Errorf("read response failed: %v", err)
	}

	var tokenResp TokenResponse
	if err := json.Unmarshal(body, &tokenResp); err != nil {
		return "", "", 0, 0, fmt.Errorf("unmarshal response failed: %v", err)
	}

	if tokenResp.Code != 200 {
		return "", "", 0, 0, fmt.Errorf("get token failed: %s", tokenResp.Msg)
	}

	// 处理refresh_token，可能为null
	var refreshToken string
	if tokenResp.Data.RefreshToken != nil {
		if str, ok := tokenResp.Data.RefreshToken.(string); ok {
			refreshToken = str
		}
	}

	// 处理refresh_expire_in，可能为null
	var refreshExpireIn int64
	if tokenResp.Data.RefreshExpireIn != nil {
		if num, ok := tokenResp.Data.RefreshExpireIn.(float64); ok {
			refreshExpireIn = int64(num)
		}
	}

	return tokenResp.Data.AccessToken, refreshToken, tokenResp.Data.ExpireIn, refreshExpireIn, nil
}

// TestConnection 测试连接
func (h *HlPayUtils) TestConnection() error {
	_, _, _, _, err := h.GetAccessToken()
	return err
}
